home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q1082.dms / q1082.adf / src.lzh / Fig / scale.c < prev    next >
C/C++ Source or Header  |  1991-07-18  |  8KB  |  337 lines

  1. /* 
  2.  *    FIG : Facility for Interactive Generation of figures
  3.  *
  4.  *    Copyright (c) 1985 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
  5.  *    January 1985.
  6.  *    1st revision : Aug 1985.
  7.  *
  8.  *    %W%    %G%
  9. */
  10. #include "fig.h"
  11. #include "resources.h"
  12. #include "func.h"
  13. #include "object.h"
  14. #include "paintop.h"
  15.  
  16. #define            TOLERANCE    7
  17. /*#define            min(a, b)    (((a) < (b)) ? (a) : (b))*/
  18. /*#define            max(a, b)    (((a) > (b)) ? (a) : (b))*/
  19. #define            round(a)    (int)(a + 0.5)
  20.  
  21. extern int        fix_x, fix_y, cur_x, cur_y;
  22. extern F_pos        last_position, new_position;  /* used in undo */
  23.  
  24. extern F_compound    *compound_point_search(), *compound_search();
  25. extern            (*canvas_kbd_proc)();
  26. extern            (*canvas_locmove_proc)();
  27. extern            (*canvas_leftbut_proc)();
  28. extern            (*canvas_middlebut_proc)();
  29. extern            (*canvas_rightbut_proc)();
  30. extern            null_proc();
  31. extern            set_popupmenu();
  32.  
  33.             prescale_compound(), elastic_compoundbox();
  34.  
  35. static enum        {WEST, NORTH, EAST, SOUTH, CORNER} side;
  36. static int        save_coord;
  37. static F_compound    *compound;
  38. static double        cosa, sina;
  39. static int        fromx, fromy;
  40.             init_scale_compound();
  41.  
  42. scale_compound_selected()
  43. {
  44.     canvas_kbd_proc = null_proc;
  45.     canvas_locmove_proc = null_proc;
  46.     canvas_leftbut_proc = init_scale_compound;
  47.     canvas_middlebut_proc = null_proc;
  48.     canvas_rightbut_proc = set_popupmenu;
  49.     set_cursor(&pick15_cursor);
  50.     reset_action_on();
  51.     }
  52.  
  53. init_scale_compound(x, y)
  54. int    x, y;
  55. {
  56.     double    dx, dy, l;
  57.     
  58.     if ((compound = compound_point_search(x, y, TOLERANCE, &cur_x,
  59.                           &cur_y)) != NULL)
  60.     {
  61.         if (compound->nwcorner.x == cur_x) 
  62.             fix_x = compound->secorner.x;
  63.         else
  64.             fix_x = compound->nwcorner.x;
  65.         if (compound->nwcorner.y == cur_y) 
  66.             fix_y = compound->secorner.y;
  67.         else
  68.             fix_y = compound->nwcorner.y;
  69.         
  70.         side = CORNER;
  71.         dx = cur_x - fix_x;  dy = cur_y - fix_y;
  72.         l = sqrt(dx*dx + dy*dy);
  73.         cosa = fabs(dx / l);  sina = fabs(dy / l);
  74.         
  75.         fromx = cur_x;  fromy = cur_y;
  76.         win_setmouseposition(canvas_swfd, cur_x, cur_y);
  77.         draw_compoundbox(compound, INV_PAINT);
  78.         draw_rectbox(fix_x, fix_y, cur_x, cur_y, INV_PAINT);
  79.         set_latestcompound(compound);
  80.         canvas_locmove_proc = elastic_compoundbox;
  81.         canvas_middlebut_proc = prescale_compound;
  82.         canvas_leftbut_proc = canvas_rightbut_proc = null_proc;
  83.         set_action_on();
  84.         set_temp_cursor(&null_cursor);
  85.         win_setmouseposition(canvas_swfd, x, y);
  86.     }
  87.     else if ((compound = compound_search(x, y, TOLERANCE, &cur_x, &cur_y))
  88.          != NULL )
  89.     {
  90.         /* figure out which side the cursor is close to. */
  91.         if (compound->nwcorner.x == cur_x)
  92.             side = WEST;
  93.         else if (compound->nwcorner.y == cur_y)
  94.             side = NORTH;
  95.         else if (compound->secorner.x == cur_x)
  96.             side = EAST;
  97.         else if (compound->secorner.y == cur_y)
  98.             side = SOUTH;
  99.         else
  100.             return;
  101.         
  102.         /* figure out a fixed point of the compound for scaling */
  103.         switch (side) {
  104.         case WEST:
  105.         case NORTH:
  106.             fix_x = compound->secorner.x;
  107.             fix_y = compound->secorner.y;
  108.             cur_x = compound->nwcorner.x;
  109.             cur_y = compound->nwcorner.y;
  110.             break;
  111.         case EAST:
  112.         case SOUTH:
  113.             fix_x = compound->nwcorner.x;
  114.             fix_y = compound->nwcorner.y;
  115.             cur_x = compound->secorner.x;
  116.             cur_y = compound->secorner.y;
  117.             break;
  118.         }
  119.         
  120.         /* save initial corner position */
  121.         fromx = cur_x;  fromy = cur_y;
  122.         /* save x or y coordinate for restoring the cursor */
  123.         /* at the end of the scaling */
  124.         switch (side) {
  125.         case NORTH: case SOUTH:
  126.             save_coord = x;
  127.             break;
  128.         case EAST: case WEST:
  129.             save_coord = y;
  130.             break;
  131.         }
  132.         /*  erase the compound box. */
  133.         win_setmouseposition(canvas_swfd, cur_x, cur_y);
  134.         draw_compoundbox(compound, INV_PAINT);
  135.         draw_rectbox(fix_x, fix_y, cur_x, cur_y, INV_PAINT);
  136.         set_latestcompound(compound);
  137.         canvas_locmove_proc = elastic_compoundbox;
  138.         canvas_middlebut_proc = prescale_compound;
  139.         canvas_leftbut_proc = canvas_rightbut_proc = null_proc;
  140.         set_action_on();
  141.         set_temp_cursor(&null_cursor);
  142.         win_setmouseposition(canvas_swfd, x, y);
  143.     }
  144. }
  145.  
  146.  
  147. elastic_compoundbox(x, y)
  148. int    x, y;
  149. {
  150.     draw_rectbox(fix_x, fix_y, cur_x, cur_y, INV_PAINT);
  151.     compute_adjustposition(x, y);
  152.     win_setmouseposition(canvas_swfd, cur_x, cur_y);
  153.     draw_rectbox(fix_x, fix_y, cur_x, cur_y, INV_PAINT);
  154.     }
  155.  
  156. compute_adjustposition(x, y)
  157. int    x, y;
  158. {
  159.     double    xx, yy, d;
  160.  
  161.     switch(side) {
  162.     case CORNER:
  163.         xx = x - fix_x;
  164.         yy = y - fix_y;
  165.         d = sqrt(xx*xx + yy*yy);
  166.         if (xx < 0)
  167.             cur_x = fix_x - round(d * cosa);
  168.         else
  169.             cur_x = fix_x + round(d * cosa);
  170.         if (yy < 0)
  171.             cur_y = fix_y - round(d * sina);
  172.         else
  173.             cur_y = fix_y + round(d * sina);
  174.         break;
  175.     case NORTH:
  176.     case SOUTH:
  177.         cur_y = y;
  178.         break;
  179.     case EAST:
  180.     case WEST:
  181.         cur_x = x;
  182.         break;
  183.     }
  184. }
  185.  
  186. prescale_compound(x, y)
  187. int    x, y;
  188. {
  189.     float        scalex, scaley;
  190.  
  191.     draw_rectbox(fix_x, fix_y, cur_x, cur_y, INV_PAINT);
  192.     compute_adjustposition(x, y);
  193.     erase_compound(compound);
  194.  
  195.     scalex = ((float) (cur_x - fix_x)) / (fromx - fix_x);
  196.     scaley = ((float) (cur_y - fix_y)) / (fromy - fix_y);
  197.     scale_compound(compound, scalex, scaley, fix_x, fix_y);
  198.  
  199.     draw_compound(compound);
  200.     draw_compoundbox(compound, INV_PAINT);
  201.     last_position.x = fromx;
  202.     last_position.y = fromy;
  203.     new_position.x = cur_x;
  204.     new_position.y = cur_y;
  205.     /* update cursor position for single axis scaling. */
  206.     switch (side) {
  207.     case NORTH: case SOUTH:
  208.         /* maintain old horiz. pos. */
  209.         cur_x = save_coord;
  210.         break;
  211.     case EAST: case WEST:
  212.         /* maintain old vert. pos. */
  213.         cur_y = save_coord;
  214.         break;
  215.     }
  216.     clean_up();
  217.     set_action_object(F_SCALE, O_COMPOUND);
  218.     set_latestcompound(compound);
  219.     set_modifiedflag();
  220.     scale_compound_selected();
  221.     }
  222.  
  223. scale_compound(c, sx, sy, refx, refy)
  224. F_compound    *c;
  225. float        sx, sy;
  226. int        refx, refy;
  227. {
  228.     F_line        *l;
  229.     F_spline    *s;
  230.     F_ellipse    *e;
  231.     F_text        *t;
  232.     F_arc        *a;
  233.     F_compound    *c1;
  234.     int        x1, y1, x2, y2;
  235.  
  236.     x1 = round(refx + (c->nwcorner.x - refx) * sx);
  237.     y1 = round(refy + (c->nwcorner.y - refy) * sy);
  238.     x2 = round(refx + (c->secorner.x - refx) * sx);
  239.     y2 = round(refy + (c->secorner.y - refy) * sy);
  240.     c->nwcorner.x = min(x1, x2);
  241.     c->nwcorner.y = min(y1, y2);
  242.     c->secorner.x = max(x1, x2);
  243.     c->secorner.y = max(y1, y2);
  244.  
  245.     for (l = c->lines; l != NULL; l = l->next) {
  246.         scale_line(l, sx, sy, refx, refy);
  247.         }
  248.     for (s = c->splines; s != NULL; s = s->next) {
  249.         scale_spline(s, sx, sy, refx, refy);
  250.         }
  251.     for (a = c->arcs; a != NULL; a = a->next) {
  252.         scale_arc(a, sx, sy, refx, refy);
  253.         } 
  254.     for (e = c->ellipses; e != NULL; e = e->next) {
  255.         scale_ellipse(e, sx, sy, refx, refy);
  256.         }
  257.     for (t = c->texts; t != NULL; t = t->next) {
  258.         scale_text(t, sx, sy, refx, refy);
  259.         }
  260.     for (c1 = c->compounds; c1 != NULL; c1 = c1->next) {
  261.         scale_compound(c1, sx, sy, refx, refy);
  262.         }
  263.     }
  264.  
  265. scale_line(l, sx, sy, refx, refy)
  266. F_line    *l;
  267. float    sx, sy;
  268. int    refx, refy;
  269. {
  270.     F_point        *p;
  271.  
  272.     for (p = l->points; p != NULL; p = p->next) {
  273.         p->x = round(refx + (p->x - refx) * sx);
  274.         p->y = round(refy + (p->y - refy) * sy);
  275.         }
  276.     }
  277.  
  278. scale_spline(s, sx, sy, refx, refy)
  279. F_spline    *s;
  280. float        sx, sy;
  281. int        refx, refy;
  282. {
  283.     F_point        *p;
  284.     F_control    *c;
  285.  
  286.     for (p = s->points; p != NULL; p = p->next) {
  287.         p->x = round(refx + (p->x - refx) * sx);
  288.         p->y = round(refy + (p->y - refy) * sy);
  289.         }
  290.     for (c = s->controls; c != NULL; c = c->next) {
  291.         c->lx = refx + (c->lx - refx) * sx;
  292.         c->ly = refy + (c->ly - refy) * sy;
  293.         c->rx = refx + (c->rx - refx) * sx;
  294.         c->ry = refy + (c->ry - refy) * sy;
  295.         }
  296.     }
  297.  
  298. scale_arc(a, sx, sy, refx, refy)
  299. F_arc    *a;
  300. float    sx, sy;
  301. int    refx, refy;
  302. {
  303.     int        i;
  304.  
  305.     for (i = 0; i < 3; i++) {
  306.         a->point[i].x = round(refx + (a->point[i].x - refx) * sx);
  307.         a->point[i].y = round(refy + (a->point[i].y - refy) * sy);
  308.         }
  309.     compute_arccenter(a->point[0], a->point[1], a->point[2], 
  310.         &a->center.x, &a->center.y);
  311.     a->direction = compute_direction(a->point[0], a->point[1], a->point[2]);
  312.     } 
  313.  
  314. scale_ellipse(e, sx, sy, refx, refy)
  315. F_ellipse    *e;
  316. float        sx, sy;
  317. int        refx, refy;
  318. {
  319.     e->center.x = round(refx + (e->center.x - refx) * sx);
  320.     e->center.y = round(refy + (e->center.y - refy) * sy);
  321.     e->start.x = round(refx + (e->start.x - refx) * sx);
  322.     e->start.y = round(refy + (e->start.y - refy) * sy);
  323.     e->end.x = round(refx + (e->end.x - refx) * sx);
  324.     e->end.y = round(refy + (e->end.y - refy) * sy);
  325.     e->radiuses.x = round(e->radiuses.x * sx);
  326.     e->radiuses.y = round(e->radiuses.y * sy);
  327.     }
  328.  
  329. scale_text(t, sx, sy, refx, refy)
  330. F_text    *t;
  331. float    sx, sy;
  332. int    refx, refy;
  333. {
  334.     t->base_x = round(refx + (t->base_x - refx) * sx);
  335.     t->base_y = round(refy + (t->base_y - refy) * sy);
  336.     }
  337.